using System.Linq.Expressions;
using Terra.Data.Entities;

namespace Terra.Data.Repository;

/// <summary>
/// 仓储接口
/// </summary>
/// <typeparam name="TEntity">实体类型</typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
public interface IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>
{
    #region 查询
    /// <summary>
    /// 获取所有实体
    /// </summary>
    /// <returns>实体列表</returns>
    Task<List<TEntity>> GetAllAsync();

    /// <summary>
    /// 根据条件获取实体
    /// </summary>
    /// <param name="predicate">条件表达式</param>
    /// <returns>实体列表</returns>
    Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    /// 根据主键获取实体
    /// </summary>
    /// <param name="id">主键</param>
    /// <returns>实体</returns>
    Task<TEntity> GetByIdAsync(TKey id);

    /// <summary>
    /// 根据条件获取第一个实体
    /// </summary>
    /// <param name="predicate">条件表达式</param>
    /// <returns>实体</returns>
    Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    /// 获取查询对象
    /// </summary>
    /// <returns>查询对象</returns>
    IQueryable<TEntity> GetQueryable();
    #endregion

    #region 新增
    /// <summary>
    /// 新增实体
    /// </summary>
    /// <param name="entity">实体</param>
    /// <returns>实体</returns>
    Task<TEntity> InsertAsync(TEntity entity);

    /// <summary>
    /// 批量新增实体
    /// </summary>
    /// <param name="entities">实体列表</param>
    /// <returns>实体列表</returns>
    Task<List<TEntity>> InsertRangeAsync(IEnumerable<TEntity> entities);
    #endregion

    #region 更新
    /// <summary>
    /// 更新实体
    /// </summary>
    /// <param name="entity">实体</param>
    /// <returns>实体</returns>
    Task<TEntity> UpdateAsync(TEntity entity);

    /// <summary>
    /// 批量更新实体
    /// </summary>
    /// <param name="entities">实体列表</param>
    /// <returns>实体列表</returns>
    Task<List<TEntity>> UpdateRangeAsync(IEnumerable<TEntity> entities);
    #endregion

    #region 删除
    /// <summary>
    /// 删除实体
    /// </summary>
    /// <param name="entity">实体</param>
    /// <returns>是否成功</returns>
    Task<bool> DeleteAsync(TEntity entity);

    /// <summary>
    /// 根据主键删除实体
    /// </summary>
    /// <param name="id">主键</param>
    /// <returns>是否成功</returns>
    Task<bool> DeleteByIdAsync(TKey id);

    /// <summary>
    /// 批量删除实体
    /// </summary>
    /// <param name="entities">实体列表</param>
    /// <returns>是否成功</returns>
    Task<bool> DeleteRangeAsync(IEnumerable<TEntity> entities);
    #endregion

    #region 其他
    /// <summary>
    /// 检查是否存在
    /// </summary>
    /// <param name="predicate">条件表达式</param>
    /// <returns>是否存在</returns>
    Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    /// 获取总数
    /// </summary>
    /// <param name="predicate">条件表达式</param>
    /// <returns>总数</returns>
    Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate = null);
    #endregion
}